<template>
  <div :style="{display:activeContact?'':'none'}">
    <div class="luckim-chat-box cc-layer luckim-unselect drag22 kim-chat-box" ref="box"
         :style="chatboxStyle" v-show="store.state.chatboxShow"
         state="normal">
      <div class="luckim-background kim-c-bg" :style="{'background-image':'url('+store.state.skinImg+')'}"></div>
      <div class="chatbox-title drag21"></div>
      <div style="" class="cc-layer-btns">
        <li><span class="iconfont" @click="zuixiaohua">&#xe68f;</span></li>
        <li><span class="iconfont" @click="maximum=!maximum">{{ maximum ? '&#xe692;' : '&#xe6c0;' }}</span></li>
        <li><span class="iconfont" @click="close">&#xe66e;</span></li>
      </div>
      <div class="kim-chat-menu" :style="{width:sx.menu.width+'px'}" v-show="showMenu">
        <li :id="'menu-item-'+fr.type+''+fr.id" v-for="fr in list"
            :cid="fr.id" :ctype="fr.type" @click="active(fr.type,fr.id)"
            :class="[(fr.type+fr.id)==activeId?'active':'',]">
          <img :src="fr.avatar" alt="" :class="[fr.state==0?'filter-gray':'']">
          <span name="" :title="fr.name">{{ fr.name }}</span>
          <span icon="" class="iconfont" @click.stop="closeChat(fr.id)">&#xe67d;</span>
        </li>

      </div>
      <div class="luckim-chat-list kim-rbox" :style="rightStyle">
        <div class="luckim-chat" :id="'kim-chat-'+fr.type+''+fr.id"
             v-for="fr in chating" v-show="(fr.type+fr.id)==activeId"
             :uid="fr.id" :type="fr.type" :style="{height:sx.box.height+'px'}">
          <div class="kim-fr-t">
            <span style="font-size:18px">{{ fr.name }}</span>
            <span class="kim-co-state" :style="{color:['','#3c9840',''][fr.state]}">
              {{ ['离线', '在线', '繁忙'][fr.state] }}</span>
            <span v-if="fr.type=='group'">({{ '群聊' }})</span>
            <span v-if="fr.type=='friend'">({{ '好友' }})</span>
            <span v-if="fr.type=='member'">({{ '来自群聊' }})</span>

            <!-- 查询群成员 -->
            <span :class="['kim-gsbtn','iconfont',gs[fr.id]?'icon-arrow-up-bold':'icon-arrow-down-bold']"
                  v-show="fr.type=='group'" @click="onMembersClick(fr.id)"></span>
          </div>
          <!-- 聊天消息区域 -->
          <div class="luckim-chat-main" :style="boxStyle" :chatmain="fr.type+''+fr.id">
            <transition name="fade">
              <!-- 群员列表 -->
              <div class="kim-qybox" :style="qyboxStyle" v-show="gs[fr.id]" v-if="fr.type=='group'">
                <div class="member" v-for="mo in groupMembers[fr.id]"
                     :title="mo.name" @click="onMemberClick(mo)">
                  <img :src="mo.avatar" alt="">
                  <!--                <div>{{ mo.name }}</div>-->
                </div>
              </div>
            </transition>
            <div style="padding:10px">
              <!--
              msg{ type,id,fromid,name,avatar,content,mine,timestamp }
              -->
              <li v-for="(msg,index) in chatlog(fr.type,fr.id)" :key="index">
                <div :class="[msg.mine?'luc-msg-r':'luc-msg-l']" v-if="!msg.system">
                  <div class="luckim-msg-user">
                    <img :src="msg.avatar" alt="">
                    <span class="info">
                    <span class="name">{{ msg.name }}</span>
                    <span class="time">{{ dateformat(msg.timestamp) }}</span>
                  </span>
                  </div>
                  <div class="luckim-chat-text" v-html="xss(msg.content)" v-if="msgtype(msg)=='text'"></div>
                  <div class="luckim-chat-text file" v-html="xss(msg.content)" v-if="msgtype(msg)=='file'"></div>
                  <div class="luckim-chat-text img" v-html="xss(msg.content)" v-if="msgtype(msg)=='img'"></div>
                </div>
                <div class="kim-msg-system" v-if="msg.system">
                  <span>{{ msg.content }}</span>
                </div>
              </li>
            </div>
          </div>
          <!-- 编辑器区域 -->
          <div class="luckim-chat-editor" :style="editorStyle">
            <EditorToolbar :activeContact="activeContact"></EditorToolbar>
            <div class="luckim-editor-textarea">
              <textarea class="txarea" spellcheck="false" :style="textareaStyle"
                        @input="onEditorInput($event,fr)"></textarea>
              <!-- <div class="txarea" contenteditable="true"></div>-->
            </div>
            <div class="luckim-editor-footer" :style="{height:sx.footerHeight+'px'}">
              <div class="editor-btns">
                <button class="lc-btn lc-btn-success btn-send" @click="send(fr)">发送</button>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="kim-chat-resize" @mousedown="onResize" v-show="!maximum"><span class="iconfont">&#xea38;</span></div>
    </div>

    <div id="kim-zxh-box" :style="{display:minimum?'':'none'}" @click="minimum=false">
      {{ chating.length }}个对话已折叠
    </div>

    <viewer ref="viewer"></viewer>
  </div>
</template>

<script>
import {drag, selectionEmpty} from "@/kim/utils/utils";
import store from "@/kim/store";
import event from '@/kim/utils/event'
import rich from '@/kim/utils/RichParser'
import {dateformat} from "@/kim/utils/dateformat";
import Viewer from "@/kim/components/viewer";
import EditorToolbar from "@/kim/editor-toolbar";

const jQuery = window['jQuery'];

const defaultSx = { //界面属性
  menu: { //左侧区域
    width: 0,
  },
  box: { //右侧区域，不包含标题高度
    width: 600,
    height: 540,
  },
  titleHeight: 40,     //标题栏高度
  toolbarHeight: 37,   //工具栏高度
  textareaHeight: 118, //文本框高度
  footerHeight: 40,    //底部区域高度
  main: {  //主框属性，所有内部组件尺寸都应该根据此属性计算得出
    //width:600,      //主框宽度
    //height:580,     //主框高度
    top: 0,
    left: 0,
  },
  mbox: { //消息区域

  },
  minWidth: 460,
  minHeight: 360,
};


export default {
  name: "chatbox",
  components: {EditorToolbar, Viewer},
  data() {
    return {
      activeId: 0, //friend1001,group1001
      activeContact: null, //当前聊天的好友或群
      //list:[],//正在进行的聊天
      sx: JSON.parse(JSON.stringify(defaultSx)),
      maximum: false,  //是否最大化
      minimum: false,  //是否最小化
      gs: { //各个群聊的群员面板状态
      },
      //群成员
      groupMembers: {
        '群id': [],//成员列表
      },
      windowWidth: window.innerWidth,  //窗口宽度
      windowHeight: window.innerHeight, //窗口高度
      editmsg: {
        'type+id': {el: null, text: ''}
      },
      inited: false, //是否已经初始化过
    }
  },
  mounted() {
    let that = this;
    store.state.chatboxInstance = that;
    //如果未初始化过，则初始化监听器
    if (!that.inited) {
      new drag('.drag21', '.drag22', 'window', function (left, top) {
        that.sx.main.top = top;
        that.sx.main.left = left;
      });
      window.addEventListener("resize", function (ev) {
        that.windowWidth = window.innerWidth;
        that.windowHeight = window.innerHeight;
      });

      console.log('初始化监听器');

      //事件监听：当消息图片双击
      event.on('msg-img-dblclick', (el) => {
        that.$refs.viewer.open(el.src);
      })
    }



  },
  methods: {
    //选择图片的回调
    imageLoaded(url) {
      let act = this.activeContact;
      console.log(act)
      this.newMessage({
        type: act.type,   //聊天类型
        id: act.id,       //在和谁聊天
        fromid: this.mine.id, //发送者id
        name: this.mine.name, //发送者名字
        avatar: this.mine.avatar, //发送者头像
        content: '[img:'+url+']',   //消息内容
        mine: true,      //是否自己，影响左右显示
        timestamp: new Date().getTime(), //发送时间
      });
      let res = {
        mine: this.mine,
        to: this.activeContact,
        content: '[img:'+url+']',
      };
      this.$store.state.kimInstance.$emit('on-send', res);
    },
    addMessage(res) {
      let mine = res.mine;
      let to = res.to;

      this.newMessage({
        type: res.to.type,   //聊天类型
        id: res.to.id,       //在和谁聊天
        fromid: mine.id, //发送者id
        name: mine.name, //发送者名字
        avatar: mine.avatar, //发送者头像
        content: res.content,   //消息内容
        mine: true,      //是否自己，影响左右显示
        timestamp: new Date().getTime(), //发送时间
      })
    },

    zuixiaohua() {
      this.maximum = false;
      this.minimum = true;

    },
    // 群员被点击
    onMemberClick(member) {
      member.type = 'member';
      console.log('群员被点击', member);
      this.$emit('group-member-click', member);
      event.fire('group-member-click', [member]);
      this.chat(member);
    },
    dateformat(timestamp, fmt) {
      return dateformat(new Date(timestamp), fmt);
    },
    msgtype(msg) {
      let content = msg.content;
      if (rich.isOnlyFile(content)) {
        return 'file';
      }
      if (rich.isOnlyImage(content)) {
        return 'img';
      }
      return 'text';
    },
    //查询群成员列表
    onMembersClick(gid) {
      let that = this;
      let open = !this.gs[gid];
      this.$set(this.gs, gid, open);
      if (open) {
        let cfg = store.state.config;
        jQuery.ajax({
          url: cfg.members.url,
          type: cfg.members.type||'get',
          data: {
            id: gid, ...cfg.members.data
          },
          success: function (res) {
            if (res.code == 0) {
              let list = res.data;
              that.$set(that.groupMembers, gid, list);
            }
          }
        });

      }
    },
    xss(content) {

      let html = content;

      html = html.replace(/\</g, '&lt;')
          .replace(/\>/g, '&gt;')
          .replace(/ /g, '&nbsp;')
          .replace(/\n/g, '<br>');

      if (rich.checkImage(html)) {
        html = rich.ImageHandle(html);
      }

      if (rich.checkFile(html)) {
        html = rich.FileHandle(html);
      }

      return html;
    },
    onEditorInput(ev, fo) {
      let key = fo.type + '' + fo.id;
      let edo = this.editmsg[key] = this.editmsg[key] || {};
      edo.text = ev.target.value;
      edo.el = ev.target;
      this.$set(this.editmsg, key, edo);
    },
    /* 窗口抖动，duration持续毫秒数 */
    shake(duration) {
      let type = this.activeContact.type;
      //群聊禁止抖动
      if (type == 'group') {
        return;
      }
      //抖动的具体实现
      let start = new Date().getTime();
      let box = this.$refs.box;
      let x = box.offsetLeft;
      let y = box.offsetTop;
      let t = setInterval(function () {
        let _x = x + parseInt(Math.random() * 40) - 20;
        let _y = y + parseInt(Math.random() * 40) - 20;
        if (Date.now() - start >= duration) {
          clearInterval(t);
          _x = x;
          _y = y;
        }
        box.style.left = _x + 'px';
        box.style.top = _y + 'px';

      }, 33);
      //添加聊天界面的抖动提示
      this.newMessage({
        system:true,
        type:type,  //用于定位聊天
        id: this.activeContact.id,     //用于定位聊天
        content: "你发送了一个抖动",
      })
      //触发抖动事件
      let res = {
        mine: this.mine,
        to: this.activeContact,
        content: '[shake]',
      };
      this.$store.state.kimInstance.$emit('on-send', res);
      this.$emit('on-shake');
      this.$store.state.kimInstance.$emit('on-shake');
    },
    /**
     * 添加聊天信息
     * @param data {type,id,fromid,name,avatar,content,mine,timestamp }
     */
    newMessage(data) {
      let that = this;
      store.commit('addMessage', data);
      that.$forceUpdate();
    },
    // 给目标发送消息
    send(fo) {
      let key = fo.type + '' + fo.id;
      let edo = this.editmsg[key] = this.editmsg[key] || {};
      if (!edo.text) {
        return;
      }
      let res = {
        mine: this.mine,
        to: fo,
        content: edo.text,
      };

      this.newMessage({
        type:fo.type,  //用于定位聊天
        id: fo.id,     //用于定位聊天
        fromid: this.mine.id, //发送者id
        name: this.mine.name, //发送者名字
        avatar: this.mine.avatar, //发送者头像
        content: edo.text,   //消息内容
        mine: true,      //是否自己，影响左右显示
        timestamp: new Date().getTime(), //发送时间
      });

      event.fire('sendMessage',[res])
      this.$emit('on-send', res);
      edo.text = edo.el.value = '';

    },
    onResize(e) {
      selectionEmpty();
      let sx = this.sx;
      let box = sx.box;
      let originWidth = box.width;
      let originHeight = box.height;
      let originX = e.pageX;
      let originY = e.pageY;

      let mousemove = function (e) {
        let x = e.pageX - originX;
        let y = e.pageY - originY;
        let w = originWidth + x;
        let h = originHeight + y;
        if (w < sx.minWidth) w = sx.minWidth;
        if (h < sx.minHeight) h = sx.minHeight;
        box.width = w;
        box.height = h;
      };
      let mouseup = function (e) {
        document.removeEventListener('mousemove', mousemove);
        document.removeEventListener('mouseup', mouseup);
      };
      document.addEventListener('mousemove', mousemove);
      document.addEventListener('mouseup', mouseup);
    },
    close() {
      store.state.chatboxShow = false;
      this.reset();
      this.list.splice(0);
      this.gs = {};
    },
    reset() { //重置位置和大小
      this.sx = JSON.parse(JSON.stringify(defaultSx));
      this.sx.main.top = (this.windowHeight - 580) / 2;
      this.sx.main.left = (this.windowWidth - 600) / 2;
      this.maximum = false;
    },
    active(type, id) {
      this.activeId = (type + id);
    },
    chat(friend) { //{type,id,name,avatar}
      if (this.chating.length == 0) {
        this.reset();
      }
      let list = this.chating;
      let user = null; //聊天目标
      for (let u of list) {
        if (u.id == friend.id) {
          user = u;
        }
      }
      //如果目标不存在
      if (!user) {
        list.push(friend);
        store.commit('addChat', friend);
      }
      //激活菜单按钮
      this.active(friend.type, friend.id);
      store.state.chatboxShow = true;
      //显示面板
      this.minimum = false;
    },
    moveTo(x, y) {
      if (this.maximum) return;
      let w = this.$refs.box.clientWidth;
      let h = this.$refs.box.clientHeight;
      if (x=='center'){
        x=(window.innerWidth - w) / 2;
        y=(window.innerHeight - h) / 2;
        return;
      }
      this.sx.main.left = x;
      this.sx.main.top = y;
    },
    closeChat(friendId) {
      let arr = this.list;
      for (let i in this.list) {
        let user = arr[i];
        if (user.id == friendId) {
          arr.splice(i, 1);
          //如果关闭的是正在激活的
          if (user.type + user.id == this.activeId) {
            let u = arr[i];
            if (i == arr.length) {
              u = arr[arr.length - 1];
            }
            this.active(u.type, u.id);

          }
          /*if (arr.length == 0) {
            store.state.chatboxShow=false;
          }*/
          break;
        }
      }
    },
    scrollToBottom(type, id) {
      console.log('滚动到底部：' + type + id)
      this.$nextTick(() => {
        let container = this.$el.querySelector("[chatmain='" + type + '' + id + "']");
        if (!container) return;
        container.scrollTop = container.scrollHeight;
        setTimeout(() => {
          container.scrollTop = container.scrollHeight;
        }, 6)
      })
    },
  }
  ,
  computed: {
    mine() {
      return store.state.mine;
    }
    ,
    friends() {
      return store.state.friends;
    }
    ,
    groups() {
      return store.state.groups;
    }
    ,
    chats() {
      return store.state.chats;
    }
    ,
    store() {
      return store;
    }
    ,
    chating() {
      return store.state.chating;
    }
    ,
    list() {
      return this.chating;
    }
    ,
    showMenu() {
      if (this.chating.length > 1) {
        if (this.maximum) {
          this.sx.menu.width = 240;
        } else {
          this.sx.menu.width = 200;
        }
      } else {
        this.sx.menu.width = 0;
      }
      return this.chating.length > 1;
    }
    ,
    data() {
      return store.state.data;
    }
    ,
    chatlog() {
      let that = this;
      return (type, id) => {
        let d = store.state.data;
        let a = d[that.mine.id];
        if (a) {
          let b = a['chatlog'];
          if (b) {
            let c = b[type + id];
            if (c) {
              return c;
            }
          }
        }

      }
    }
    ,
    chatboxStyle() {
      let ret = {};
      if (this.maximum) {
        ret.width = this.windowWidth + 'px';
        ret.height = this.windowHeight + 'px';
        ret.top = 0;
        ret.left = 0;
      } else {
        ret.width = (this.sx.menu.width + this.sx.box.width) + 'px';
        ret.height = (this.sx.box.height + this.sx.titleHeight) + 'px';
        ret.top = this.sx.main.top + 'px';
        ret.left = this.sx.main.left + 'px';
      }
      if (this.minimum) {
        ret.display = 'none';
      }
      return ret
    }
    ,
    rightStyle() { //右侧区域，不包含标题栏
      let ret = {
        //width: this.sx.box.width+'px',
        height: this.sx.box.height + 'px',
        'margin-left': this.sx.menu.width + 'px',
      };
      if (this.maximum) {
        ret.height = (this.windowHeight - this.sx.titleHeight) + 'px';
      }
      return ret;
    }
    ,
    boxStyle() {  //消息区域的样式
      let sx = this.sx;
      let h0 = (sx.toolbarHeight + sx.textareaHeight + sx.footerHeight);
      let ret = {height: (sx.box.height - h0) + 'px'};
      if (this.maximum) {
        sx.mbox.height = (this.windowHeight - sx.titleHeight - h0);
        ret.height = sx.mbox.height + 'px';
      }
      return ret;
    }
    ,
    editorStyle() { //编辑器区域的样式
      let ret = {};
      if (this.maximum) {
        //ret.height = '240px';

      }
      return ret;
    }
    ,
    textareaStyle() {
      this.sx.textareaHeight = 100;
      if (this.maximum) {
        this.sx.textareaHeight = 140;
      }
      let ret = {height: this.sx.textareaHeight + 'px'};
      return ret;
    }
    ,
    qyboxStyle() { //群员盒子样式
      let r = {
        width: this.sx.box.width + 'px',
        //height:(this.sx.box.height*0.5)+'px'
      };
      if (this.maximum) {
        r.width = (this.windowWidth - this.sx.menu.width) + 'px';
      }
      return r;
    }

  }
  ,
  watch: {
    activeId(val) {
      this.$nextTick(() => {
        this.chating.forEach((item) => {
          if (item.type + item.id == val) {
            this.activeContact = item;
            console.log('当前联系人', this.activeContact)
          }
        })
      })
    }
    ,
  }


}
</script>

<style scoped>
#kim-zxh-box {
  border: 1px solid #8a8383;
  position: fixed;
  bottom: 2px;
  left: calc(50% - 70px);
  right: 0;
  z-index: 9999;
  width: 140px;
  height: 30px;
  line-height: 30px;
  text-align: center;
  cursor: pointer;
  background: #ffffff;
}

.ml200 {
  margin-left: 200px;
}

.kim-chat-box {
  top: 185.5px;
  left: 149.5px;
  display: block;
  width: 800px;
  height: 580px;
}

.kim-chat-menu {
  height: 100%;
  position: absolute;
  left: 0px;
  top: 0px;
}


.kim-chat-menu {
  overflow-y: auto;
  background-color: #eaeaea
}

.kim-chat-menu li {
  height: 40px;
  margin: 5px;
  padding: 5px;
  display: block;
  cursor: pointer;
  border-radius: 4px;
  position: relative
}

.kim-chat-menu li:hover {
  background-color: #e5e5e5
}

.kim-chat-menu li.active {
  background-color: #f5f5f5
}

.kim-chat-menu li img {
  width: 40px;
  height: 40px;
  border-radius: 50%
}

.kim-chat-menu li [name] {
  width: 110px;
  display: inline-block;
  line-height: 40px;
  vertical-align: top;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-left: 5px;
}

.kim-chat-menu li [icon] {
  font-size: 19px;
  position: absolute;
  top: 18px;
  right: 6px;
  color: #7c7c7c;
  visibility: hidden;
  width: 19px;
  height: 19px;
}

.kim-chat-menu li:hover [icon], .kim-chat-menu li [icon]:hover {
  color: #bd1d01;
  visibility: visible
}

.kim-chat-main li {
  display: block;
  position: relative;
  margin-bottom: 10px
}

.kim-fr-t {
  height: 40px;
  background-color: #f7f7f7;
  position: absolute;
  top: 0;
  line-height: 40px;
  padding-left: 15px
}

.kim-co-state {
  font-size: 14px;
  color: #fc300d;
  margin-left: 4px
}

.kim-chat-resize {
  width: 15px;
  height: 15px;
  position: absolute;
  right: 0;
  bottom: 0;
  cursor: se-resize;
  overflow: hidden
}

.kim-chat-resize .iconfont {
  font-size: 23px;
  position: relative;
  top: -2px;
  left: -8px;
  color: #959595
}

.cc-layer-max .kim-chat-resize {
  display: none
}

.kim-qybox {
  position: absolute;
  height: 240px;
  background-color: rgb(255, 255, 255);
  background-color: rgba(255, 255, 255, .9);
  z-index: 1;
  border-bottom: 1px solid #cccccc;
  overflow-y: scroll;
  box-sizing: border-box;
  padding-left: 10px;
}

.kim-gsbtn {
  margin-left: 14px;
  cursor: pointer;
  font-size: 18px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity .3s;
}

.fade-enter, .fade-leave-to
  /* .fade-leave-active below version 2.1.8 */
{
  opacity: 0;
}

.kim-rbox {
  overflow: hidden;
}

.kim-c-bg {
  opacity: 0.1;
  background-color: rgb(255, 255, 255);
  background-size: 100%;
}

.editor-btns {
  position: absolute;
  right: 18px;
  top: -2px
}

.kim-msg-system {
  text-align: center;
  padding: 3px;
}

.kim-msg-system span {
  display: inline-block;
  line-height: 30px;
  padding: 0 15px;
  border-radius: 3px;
  background-color: #e2e2e2;
  cursor: default;
  font-size: 14px;
}

.luckim-chat-text.img {
  padding: 5px;
}

.luckim-chat-text.file {
  padding: 0;
}

.kim-qybox .member {
  width: 50px;
  height: 50px;
  display: inline-block;
  margin: 14px 0 0 15px;
  cursor: pointer;
}

.kim-qybox .member img {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  box-sizing: border-box;
  border: 1px solid #ababab;
}
</style>
